<?php
/**
 * Created by JetBrains PhpStorm.
 * User: nietao
 * Date: 13-10-21
 * Time: 上午9:48
 * To change this template use File | Settings | File Templates.
 */

namespace Forxx\Api;
use Lavender\Core;
use Lavender\Exception;

/**
 * 工具类
 * Class Utils
 * @package App\Api
 */
class Utils
{

    use ArrayListDataFilter;

    const COMPOSITE_HAS_MANY = 1;
    const COMPOSITE_BELONG_TO = 2;
    const COMPOSITE_JSON_TO_MANY = 3;
    const MAX_MYSQL_NUM = 4294967296;

    /**
     * 坐标转换
     * @param $place
     * @return array
     */
    public static function convert_place($place)
    {
        return empty($place) ? null : array(
            0 => sprintf('%.6f', $place[0]),
            1 => sprintf('%.6f', $place[1]),
        );
    }

    public static function get_random_str($length){
        $seed = "abcdefghjklmnpqrstuvwxyz023456789ABCDEFGHJKLMNPQRSTUVWXYZ";
        $max = strlen($seed) -1;
        $res = "";
        for($i = 0;$i < $length;$i++){
            $num = mt_rand(0,$max);
            $res .= substr($seed,$num,1);
        }
        return $res;
    }

    /**
     * 判断当前是否为cli模式
     * @return bool
     */
    public static function is_cli_mode(){
        $name = strtolower(php_sapi_name());
        if(strpos($name,'cli') !== false){
            return true;
        }
        return false;
    }

    /**
     * 生成格式化的token
     * @param $key
     */
    public static function makeFormatToken($key){
        $hash1 = self::get_random_str(10);
        $hash2 = self::get_random_str(40);
        $hash3 = md5(md5(md5($hash1)).md5($hash2).$key);
        return $hash1.$hash2.$hash3;
    }

    /**
     * 检查token格式
     * @param $key
     * @param $key
     */
    public static function checkTokenFormat($token,$key){
        if(strlen($token) !== 82){
            return false;
        }
        $hash1 = substr($token,0,10);
        $hash2 = substr($token,10,40);
        $hash3 = substr($token,50);
        $sign = md5(md5(md5($hash1)).md5($hash2).$key);
        return $hash3 === $sign;
    }

    /**
     * 将数组某列元素转化为key值，用作map
     */
    public static function column_to_key($column_name, $inputs = array())
    {
        $result = array();
        if (!empty($inputs)) {
            $count = count($inputs);
            for ($i = 0; $i < $count; $i++) {
                $result[$inputs[$i][$column_name]] = $inputs[$i];
            }
        }
        return $result;
    }

    /**
     * 只返回二外数组中给定的键
     * @return array
     */
    public static function array_list_by_given_keys($list = array(),$keys = array()){
        $res = [];
        foreach($list as $item){
            $tmp = [];
            foreach($keys as $key){
                $tmp[$key] = isset($item[$key])?$item[$key]:null;
            }
            $res[] = $tmp;

        }
        return $res;
    }

    /**
     * 只返回数组给定的键
     * @param array $input
     * @param array $keys
     * @return array
     */
    public static function array_filter_key($input = array(),$keys = array()){
        $length = count($keys);
        $values = array_fill(0,$length,'');
        $fill = array_combine($keys,$values);
        return array_intersect_key($input,$fill);
    }

    /**
     * 通过键值对  筛选某个符合条件的数据
     */
    public static function array_filter_by_key_value($input,array $filter){
        foreach($input as  $item){
            $isPass = true;
            foreach($filter as $key => $val){
                if((!isset($item[$key])) || $item[$key] !== $val){
                    $isPass = false;
                    break;
                }
            }
            if($isPass){
            return $item;
        }
        }
        return null;
    }

    /**
     * 通过键值对  筛选某些符合条件的数据
     */
    public static function array_filter_all_by_key_value($input,array $filter){
        return array_filter($input,function($item) use($filter) {
            foreach($filter as $key => $val){
                if((!isset($item[$key])) || $item[$key] !== $val){
                    return false;
                }
            }
            return true;
        });
    }


    /**
     * 去除数组中不需要的键
     * @param array $input
     * @param array $exclude
     * @return array
     */
    public static function array_remove_keys(array $input,array $exclude){
        $allKeys = array_keys($input);
        $usesful = array_diff($allKeys,$exclude);
        return self::array_filter_key($input,$usesful);
    }

    /**
     * [key=>val,key1=>val1]  => [[id=>key,name=>val],[id=>key1,name=>val1]]
     * @param array $inputs
     * @param string $value_name
     * @param string $key_name
     * @return array
     */
    public static function array_to_list($inputs = array(),$value_name = 'value',$key_name = 'id')
    {
        $res = [];
        foreach($inputs as $key => $val)
        {
            $res[] = [$key_name=>$key,$value_name => $val];
        }
        return $res;
    }


    /**
     * 将map的key去除，返回数组
     */
    public static function key_to_removed($inputs = array())
    {
        $result = array();
        if (!empty($inputs)) {
            foreach ($inputs as $v) {
                $result[] = $v;
            }
        }
        return $result;
    }

    public static function array_has_key($input,$key){
        if(is_array($input)){
            return array_key_exists($key,$input);
        }
        return false;
    }

    /**
     * 获取数组某列的值,返回map，去重,不包含
     */
    public static function get_column_map_exclude($column_name, $inputs = array(), $column_name_plus, $excludes = array())
    {
        $result = array();
        if (!empty($inputs)) {
            $count = count($inputs);
            $result = array();
            $excludes = self::get_column_map($column_name_plus, $excludes);
            for ($i = 0; $i < $count; $i++) {
                if (!empty($inputs[$i][$column_name]) && empty($excludes[$inputs[$i][$column_name]])) {
                    $result[$inputs[$i][$column_name]] = $inputs[$i][$column_name];
                }
            }
        }
        return $result;
    }

    /**
     * 删除数组中的某些列
     * @param $columns
     * @param array $list
     */
    public static function remove_column_key($columns,array $list){
        array_walk($list,function(&$item,$key,$unsetFields){
            foreach($unsetFields as $field){
                unset($item[$field]);
            }
        },$columns);
        return $list;
    }

    
    public static function array_value_skip($offset,$arrayMap){
        $res = [];
        foreach($arrayMap as $key => $arr){
            $res[$key] = array_slice($arr,$offset);
        }
        return $res;
    }

    /**
     * 获取数组某列的值,返回map，去重
     */
    public static function get_column_map($column_name, $inputs = array())
    {
        $result = array();
        if (!empty($inputs)) {
            $count = count($inputs);
            $result = array();
            for ($i = 0; $i < $count; $i++) {
                if (!empty($inputs[$i][$column_name])) {
                    $result[$inputs[$i][$column_name]] = $inputs[$i][$column_name];
                }
            }
        }
        return $result;
    }

    /**
     * 获取数组或map某列的值,返回数组
     */
    public static function get_column_array($column_name, $inputs = array())
    {
        $result = array();
        if (function_exists('array_column')) {
            return array_column($inputs, $column_name);
        }
        if (!empty($inputs)) {
            $result = array();
            $i = 0;
            foreach ($inputs as $k => $v) {
                $result[$i] = $v[$column_name];
                $i++;
            }
        }
        return $result;
    }

    public static function array_column_json_encode($data,$columns,$options = JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES){
        $keys = array_keys($data);
        $res = [];
        foreach($keys as $key){
            if(in_array($key,$columns)){
                $res[$key] = json_encode($data[$key],$options);
            }
            else{
                $res[$key] = $data[$key];
            }
        }
        return $res;
    }


    public static function array_column_json_decode($column_name,$inputs)
    {
        array_walk($inputs,function(&$item) use($column_name){
            if(isset($item[$column_name]))
            {
                $item[$column_name] = @json_decode($item[$column_name],true);
            }
        });
        return $inputs;
    }

    /**
     * @return array  [0] 为key   [1...] 为 value
     */
    public static function convert_to_array_key_values($data){
        if(count($data) < 1){
            return [];
        }
        $res = [];
        array_push($res,array_keys($data[0]));
        foreach($data as $d){
            array_push($res,array_values($d));
        }
        return $res;
    }

    public static function array_map_columns_intval($data,$columns){
        return self::array_map_columns($data,$columns,'intval');
    }

    public static function array_map_columns($data,$columns,$fn){
        array_walk($data,function(&$item) use($columns,$fn){
            $values = [];
            foreach($columns as $col){
                $values[] = $item[$col];
            }
            $values = array_map($fn,$values);
            $res = array_combine($columns,$values);
            $item = array_merge($item,$res);
        });
        return $data;
    }

    public static function array_columns_json_decode($column_names,$inputs)
    {
        array_walk($inputs,function(&$item) use($column_names){
            foreach($column_names as $column_name){
                if(isset($item[$column_name]))
                {
                    $item[$column_name] = @json_decode($item[$column_name],true);
                }
            }
        });
        return $inputs;
    }

    /**
     * 获取数组某列做为key分组map
     * @param $column_name
     * @param array $inputs
     * @return array
     */
    public static function get_group_map($column_name, $inputs = array())
    {
        $result = array();
        if (!empty($inputs)) {
            $count = count($inputs);
            $result = array();
            for ($i = 0; $i < $count; $i++) {
                $key = $inputs[$i][$column_name];
                if (!empty($key)) {
                    //unset($inputs[$i][$column_name]);
                    $result[$key][] = $inputs[$i];
                }
            }
        }
        return $result;
    }

    /**
     * 更符合需要的合并两个数组(递归,不能用原生索引)
     * @param array $arr1
     * @param array $arr2
     * @return array
     */
    public static function array_smart_merge(array $arr1,array $arr2){
        $result = [];
        $allKey = array_merge(array_keys($arr1),array_keys($arr2));
        foreach ($allKey as $key) {
            $val = isset($arr2[$key]) ? $arr2[$key] : $arr1[$key] ;
            if(!is_array($val)){
                $result[$key] = $val;
            }else{
                if(isset($arr1[$key]) && isset($arr2[$key])){
                    $result[$key] = self::array_smart_merge($arr1[$key],$arr2[$key]);
                }
                else if(isset($arr1[$key])){
                    $result[$key] = $arr1[$key];
                }
                else{
                    $result[$key] = $arr2[$key];
                }
            }
        }
        return $result;
    }

    /**
     * 数组去重
     */
    public static function array_smart_unique($arr)
    {
        if (empty($arr)) {
            return $arr;
        }
        return array_values(array_unique($arr));
    }

    /**
     * 数组填充为指定长度
     */
    public static function array_pad($arr,$len,$val,$padType = STR_PAD_LEFT){
        $count = count($arr);
        if($count >= $len){
            return $arr;
        }
        $fill = array_fill(0,$len - $count,$val); 
        if($padType == STR_PAD_LEFT){  
            foreach($fill as $item){
                array_unshift($arr,$item);
            }
        }
        else{
            foreach($fill as $item){
                array_push($arr,$item);
            }
        }
        return $arr;
    }

    /**
     * 
     */
    public static function make_mutil_array($keys,$arr1){
        $keyLength = count($keys);
        $argc = func_num_args();
        $argv = func_get_args();
        if($keyLength !== $argc -1){
            throw new Exception('error format input data');
        }
        $res = [];
        $count = count($arr1);
        for($i = 0;$i < $count;$i++){
            $currentValues = [];
            for($j = 0;$j<$keyLength;$j++){
                $currentValues[] = $argv[$j+1][$i];
            }
            $res[] = array_combine($keys,$currentValues);
        }
        return $res;
    }


    /**
     * @param string $column_name
     * @param array $input
     * @param array $must_exists
     * @param array $must_not_exists
     * @return array
     */
    public static function filter_by_column($column_name, $inputs = [], $must_exists = [], $must_not_exists = [])
    {
        $result = [];
        if (count($must_exists) < 1) {
            return $result;
        }
        foreach ($inputs as $input) {
            $check = $input[$column_name];
            if ((!in_array($check, $must_exists, true)) || in_array($check, $must_not_exists, true)) {
                continue;
            }
            $result[] = $input;
        }
        return $result;
    }

    /**
     * 将给定的数组按照给定键值排序
     * @param array $records
     * @param array $ids
     * @param string $record_key
     * @return multitype:Ambigous <unknown>
     */
    public static function sort_by_given_ids($records, $ids, $record_key = "id")
    {
        $res = [];
        $replace_data = self::column_to_key($record_key, $records);
        foreach ($ids as $id) {
            if (isset($replace_data[$id])) {
                $res[] = $replace_data[$id];
            }
        }
        return $res;
    }

    /**
     * 将给定的数组按照给定键值排序
     * @param array $records
     * @param array $ids
     * @param string $record_key
     * @return multitype:Ambigous <unknown>
     */
    public static function sort_by_given_keys($records, $keys)
    {
        $res = [];
        foreach ($keys as $key) {
            if (isset($records[$key])) {
                $res[] = $records[$key];
            }
        }
        return $res;
    }

    /**
     * @param array $records
     * @param string $column_name
     * @param int $sort_flag
     */
    public static function sort_by_key($records, $column_name, $sort_flag = SORT_DESC)
    {
        if ($sort_flag !== SORT_ASC) {
            $sort_flag = SORT_DESC;
        }
        $columns = array_column($records, $column_name);
        array_multisort($columns, SORT_NUMERIC | $sort_flag, $records);
        return array_values($records);
    }

//        composite dome
//        $base = [
//        ['id'=>1,'uid'=>10,'type_id'=>1,'name'=>'真心英雄','second'=>246],
//        ['id'=>2,'uid'=>2,'type_id'=>2,'name'=>'皇后大道东','second'=>360],
//        ['id'=>3,'uid'=>6,'type_id'=>1,'name'=>'少年壮志不言愁','second'=>118],
//        ];
//
//        $user = [
//        ['id'=>2,'username'=>'3755@qq.com', 'nickname'=>'foxxx','role_access_id'=>1,'platform_id'=>3],
//        ['id'=>6,'username'=>'1284@qq.com', 'nickname'=>'电影忍者','role_access_id'=>2,'platform_id'=>1],
//        ['id'=>8,'username'=>'492@qq.com', 'nickname'=>'大意','role_access_id'=>2,'platform_id'=>1],
//        ['id'=>10,'username'=>'469@qq.com', 'nickname'=>'王叔叔','role_access_id'=>1,'platform_id'=>2],
//        ];
//        $type = [
//        ['id'=>1,'name'=>'网易云音乐',],
//        ['id'=>2,'name'=>'酷狗音乐',],
//        ['id'=>3,'name'=>'虾米音乐',],
//        ];
//
//        $role = [
//        ['id'=>1,'access'=>1,'role'=>'user','desc'=>'VIP'],
//        ['id'=>2,'access'=>1,'role'=>'guest','desc'=>'游客'],
//        ['id'=>3,'access'=>2,'role'=>'admin','desc'=>'管理员'],
//        ['id'=>4,'access'=>2,'role'=>'develop','desc'=>'开发者'],
//        ['id'=>5,'access'=>3,'role'=>'third','desc'=>'其他平台用户'],
//        ];
//
//        $platform = [
//        ['id'=>1,'role'=>'wx','desc'=>'微信'],
//        ['id'=>2,'role'=>'weibo','desc'=>'微博'],
//        ['id'=>3,'role'=>'taobao','desc'=>'淘宝'],
//        ['id'=>4,'role'=>'google','desc'=>'Google'],
//        ];
//
//        $comment = [
//        ['id'=>1,'post_id'=>'1','author_id'=>1,'uid'=>2,'comment'=>'LZSB',],
//        ['id'=>2,'post_id'=>'1','author_id'=>2,'uid'=>6,'comment'=>'楼主说的好啊',],
//        ['id'=>2,'post_id'=>'2','author_id'=>3,'uid'=>6,'comment'=>'好人一生平安',],
//        ];
//
//        $author = [
//        ['id'=>1,'uid'=>2,'author'=>'sb','desc'=>'三毛'],
//        ['id'=>2,'uid'=>2,'author'=>'59','desc'=>'莫言'],
//        ['id'=>3,'uid'=>6,'author'=>'吴承恩','desc'=>'西游'],
//        ['id'=>4,'uid'=>8,'author'=>'施耐庵','desc'=>'SB'],
//        ];
//
//        $data = Utils::composite_data($base,[
//        'user'=>[
//        'access'=>[Utils::COMPOSITE_HAS_MANY,'access','role_access_id','role'],
//        'platform'=>[Utils::COMPOSITE_BELONG_TO,'id','platform_id'],
//        Utils::COMPOSITE_BELONG_TO,'id','uid',
//        ],
//        'comment'=>[
//        'author'=>[
//        'user'=>[ Utils::COMPOSITE_BELONG_TO,'id','uid',],
//        Utils::COMPOSITE_BELONG_TO,'id','author_id'
//        ],
//        'user'=>[Utils::COMPOSITE_BELONG_TO,'id','uid',],
//        Utils::COMPOSITE_HAS_MANY,'post_id','id'
//        ],
//        'type'=>[Utils::COMPOSITE_BELONG_TO,'id','type_id'],
//        ], ['user'=>$user,'type'=>$type,'role'=>$role,'platform'=>$platform,'comment'=>$comment,'author'=>$author]);

    /**
     * 组合给定的数据
     * @param array $base
     * @param array $relations [$asKey=>[type,$selfKey,$otherKey,$extendKey]]
     * @param array $extends
     * @return array
     */
    public static function composite_data(array $base, array $relations, array $extends = [])
    {
        foreach ($relations as $as => $relation) {
            foreach ($relation as $a => $re) {
                if (is_string($a)) {
                    $extends[$as] = self::composite_data($extends[$as], [$a => $re], $extends);
                } elseif (is_int($a) && is_int($re)) {
                    $type = $re;
                    $real_relation = array_slice($relation, $a);
                    $index = $real_relation[1];
                    $to = $real_relation[2];
                    $alias = isset($real_relation[3]) ? $real_relation[3] : NULL;
                    if (empty($alias)) {
                        $alias = $as;
                    }
                    $base = self::composite_single($base, $as, $type, $index, $to, $extends[$alias]);
                    break;
                }
            }
        }
        return $base;
    }

    /**
     * 组合某一组数据
     * @param $base
     * @param $attr
     * @param $type
     * @param $index
     * @param $index_to
     * @param $extend
     * @return mixed
     */
    public static function composite_single(array $base, $attr, $type, $index, $index_to, array $extend)
    {
        $extend_idx = self::column_to_key($index, $extend);
        $extend_group_idx = self::get_group_map($index, $extend);
        foreach ($base as &$value) {
            $key = $value[$index_to];
            if ($type == self::COMPOSITE_HAS_MANY) {
                if (isset($extend_group_idx[$key])) {
                    $value[$attr] = $extend_group_idx[$key];
                } else {
                    $value[$attr] = [];
                }
            } elseif ($type == self::COMPOSITE_BELONG_TO) {
                if (isset($extend_idx[$key])) {
                    $value[$attr] = $extend_idx[$key];
                } else {
                    $value[$attr] = null;
                }
            } elseif($type == self::COMPOSITE_JSON_TO_MANY){
                $keys = @json_decode($key,true);
                $value[$attr] = [];
                if(is_array($keys))
                {
                    foreach($keys as $k)
                    {
                        if (isset($extend_idx[$k])) {
                            $value[$attr][] = $extend_idx[$k];
                        }
                    }
                }
            }

        }
        return $base;
    }

    /**
     * 时间转数字计算
     */
    public static function HHMMSS2num($time){
        $time = intval($time);
        return floor($time / 10000) * 3600 + floor(($time % 10000) /100) * 60 + ($time % 100);
    }

    /**
     * 钱单位转分int 1.23 元  => 123 分
     */
    public static function money_to_penny_int($number){
        return round(bcmul($number,"100",1));
    }

    /**
     * 金额 / 价格  转为 int
     * @param unknown $number
     * @return number
     */
    public static function price_to_int($number)
    {
        return round(floatval($number) * 1000);
    }

    /**
     * int 转为 金额 / 价格 (单位 厘)
     * @param unknown $number
     * @return number
     */
    public static function int_to_price($number)
    {
        return intval($number) / 1000;
    }

    /**
     * 格式化输入价格
     * @param array $datas
     * @param array $cols
     * @return array
     */
    public static function format_input_price($datas, $cols = [])
    {
        foreach ($datas as $key => &$vals) {
            if (in_array($key, $cols)) {
                $vals = self::price_to_int($vals);
            }
        }
        return $datas;
    }

    /**
     * 转换价格的显示
     * @param $datas
     * @param array $cols
     * @return mixed
     */
    public static function format_show_price($datas, $cols = [])
    {
        foreach ($datas as $key => &$vals) {
            if (is_array($vals)) {
                $vals = self::format_show_price($vals, $cols);
            } else {
                if (in_array($key, $cols)) {
                    $vals = self::int_to_price($vals);
                }
            }
        }
        return $datas;
    }

    /**
     * 中文方式显示金额
     */
    public static function format_cn_money($money){
        $money = intval($money);
        $money_str = $money . '';
        $money_first = $money_str[0] == '-' ? '-' : '';
        $money_str = trim($money_str,'-');
        $arr = [];
        do{
            $len = strlen($money_str);
            if($len <= 4){
                array_unshift($arr,$money_str);
                break;
            }
            $cur = substr($money_str,-4);
            $money_str = substr($money_str,0,-4);
            array_unshift($arr,$cur);
        }while(true);
        return $money_first.implode(",",$arr);
    }

    /**
     * @param $str
     * @param string $input_defult_price
     * @param string $output
     * @return int|string
     */
    public static function format_input_file_size($str, $input_defult_price = 'MB', $output = 'KB')
    {
        $str = trim(strtoupper($str));
        $lastChar = substr($str,-1);
        if (is_numeric($lastChar)) {
            $str = $str . $input_defult_price;
        }
        $bytes = self::get_byte($str);
        $units = ['B', 'KB', 'MB', 'GB', 'TB'];
        $index = array_search($output, $units);

        if ($index === false) {
            return $bytes;
        } else {
            return bcdiv($bytes, bcpow(1024, $index, 0), 0);
        }
    }

    /**
     * @param $str
     * @return int|string
     */
    public static function get_byte($str)
    {
        $str = str_replace(' ', '', $str);
        $str = trim(strtoupper($str));
        $str = rtrim($str, 'Bb.');
        $pattern = "/^(\d+(\.\d+)?)([KMGT]?)$/";
        $match = [];
        preg_match($pattern, $str, $match);
        if (count($match) != 4) {
            return 0;
        } else {
            $int_num = bcmul($match[1], 1, 0);
            $float_str = substr($match[2], 1, 2);
            if (empty($float_str)) {
                $float_num = 0;
            } else {
                $float_num = intval(str_pad($float_str, 2, "0", STR_PAD_RIGHT));
            }
            $unit = $match[3];
            $res = 0;
            switch ($unit) {
                case "":
                    $res = $int_num;
                    break;
                case "K":
                    $res = bcadd(bcmul($int_num, 1024), intval($float_num * 10.24), 0);
                    break;
                case "M":
                    $res = bcmul(bcadd(bcmul($int_num, 1024), intval($float_num * 10.24), 0), 1024, 0);
                    break;
                case "G":
                    $res = bcmul(bcadd(bcmul($int_num, 1024), intval($float_num * 10.24), 0), 1024 * 1024, 0);
                    break;
                case "T":
                    $res = bcmul(bcadd(bcmul($int_num, 1024), intval($float_num * 10.24), 0), 1024 * 1024 * 1024, 0);
                    break;
            }
            return $res;
        }
    }

    /**
     * @param $byte
     * @return string
     */
    public static function format_show_file_size($byte)
    {
        if (is_string($byte)) {
            $byte = self::get_byte($byte);
        }
        $num = $byte;
        $index = 0;
        do {
            $num = bcdiv($num, 1024, 2);
            $index++;
        } while (floatval($num) > 1024 && $index <= 4);
        $units = ['B', 'KB', 'MB', 'GB', 'TB'];
        return $num . $units[$index];
    }


    /**
     *  将大数字字符串转为整型  (intval 失效的情况下)
     */
    public static function to_int($num_str)
    {
        $num_str = strval($num_str);
        bcscale(0);
        return bcadd("0", $num_str);
    }

    public static function out2CSV($filename, $items, $header = [])
    {
        $fp = fopen($filename, "wb+");
        if (!empty($header)) {
            fputcsv($fp, $header);
        }
        foreach ($items as $fields) {
            fputcsv($fp, $fields);
        }
        fclose($fp);
    }

    // /**
    //  * 标点符号统一
    //  * @param $str
    //  * @return string
    //  */
    // public static function make_semiangle($str)
    // {
    //     $arr = array('０' => '0', '１' => '1', '２' => '2', '３' => '3', '４' => '4', '５' => '5', '６' => '6', '７' => '7', '８' => '8', '９' => '9', 'Ａ' => 'A', 'Ｂ' => 'B', 'Ｃ' => 'C', 'Ｄ' => 'D', 'Ｅ' => 'E', 'Ｆ' => 'F', 'Ｇ' => 'G', 'Ｈ' => 'H', 'Ｉ' => 'I', 'Ｊ' => 'J', 'Ｋ' => 'K', 'Ｌ' => 'L', 'Ｍ' => 'M', 'Ｎ' => 'N', 'Ｏ' => 'O', 'Ｐ' => 'P', 'Ｑ' => 'Q', 'Ｒ' => 'R', 'Ｓ' => 'S', 'Ｔ' => 'T', 'Ｕ' => 'U', 'Ｖ' => 'V', 'Ｗ' => 'W', 'Ｘ' => 'X', 'Ｙ' => 'Y', 'Ｚ' => 'Z', 'ａ' => 'a', 'ｂ' => 'b', 'ｃ' => 'c', 'ｄ' => 'd', 'ｅ' => 'e', 'ｆ' => 'f', 'ｇ' => 'g', 'ｈ' => 'h', 'ｉ' => 'i', 'ｊ' => 'j', 'ｋ' => 'k', 'ｌ' => 'l', 'ｍ' => 'm', 'ｎ' => 'n', 'ｏ' => 'o', 'ｐ' => 'p', 'ｑ' => 'q', 'ｒ' => 'r', 'ｓ' => 's', 'ｔ' => 't', 'ｕ' => 'u', 'ｖ' => 'v', 'ｗ' => 'w', 'ｘ' => 'x', 'ｙ' => 'y', 'ｚ' => 'z', '（' => '(', '）' => ')', '〔' => '[', '〕' => ']', '【' => '[', '】' => ']', '〖' => '[', '〗' => ']', '“' => '[', '”' => ']', '‘' => '[', '\'' => ']', '｛' => '{', '｝' => '}', '《' => '<', '》' => '>', '％' => '%', '＋' => '+', '—' => '-', '－' => '-', '～' => '-', '：' => ':', '。' => '.', '、' => ',', '，' => '.', '、' => '.', '；' => ':', '？' => '?', '！' => '!', '…' => '-', '‖' => '|', '”' => '"', '\'' => '`', '‘' => '`', '｜' => '|', '〃' => '"', '　' => ' ');
    //     return strtr($str, $arr);
    // }


    public static function touch_dir($path)
    {
        if (!is_dir($path)) {
            @mkdir($path, 0777, true);
        }
        return true;
    }

    public static function log($content, $file_name = '', $dir_name = L_APP_NAME)
    {
        $old_mask = umask(0);

        //check & make dir
        $dir = L_WORKSPACE_PATH . 'log/' . $dir_name . '/';
        if (!is_dir($dir)) {
            mkdir($dir, 0777, true);
        }

        //write file
        $file_name = empty($file_name) ? date('Ymd') : $file_name;
        $file = $dir . $file_name;
        file_put_contents($file . '.log', $content, FILE_APPEND | LOCK_EX);

        //keep small than 1G
        if (filesize($file . '.log') > 1000000000) {
            rename($file . '.log', $file . '.' . date('YmdHis') . '.log');
        }
        umask($old_mask);
    }

    /**
     * 20240524 => unixtimestamp
     */
    public static function intdate2time($day){
        $date = self::intdaytoshowdate($day);
        return strtotime($date);
    }

    /**
     * 20240524 => 2024-05-24
     */
    public static function intdaytoshowdate($day){
        if(!is_numeric($day)){
            return null;
        }
        $day = $day.'';
        if(strlen($day) != 8){
            return null;
        }
        return substr($day,0,4).'-'.substr($day,4,2).'-'.substr($day,6,2);
    }

    public static function get_time($reflush = false)
    {
        static $time = null;
        if ($reflush || empty($time)) {
            $time = time();
        }
        return $time;
    }

    public static function get_datetime($reflush = false)
    {
        static $dateStr = null;
        if ($reflush || empty($dateStr)) {
            $dateStr = date("Y-m-d H:i:s");
        }
        return $dateStr;
    }

    
    public static function parseJSONP($data,$start,$end = ");"){
        $allLen = strlen($data);
        $startLen = strlen($start);
        $endLen = strlen($end);
        if($allLen <= $startLen + $endLen){
            throw new \Exception("jsonp data is too small whith sign");
        }
        $useful = substr($data,$startLen);
        if($endLen){
            $useful = substr($useful,0,$endLen * -1);
        }        
        return @json_decode($useful,true);
    }

    /**
     * 获取毫秒级的时间戳
     */
    public static function get_ms_time(){
        return intval(bcmul(microtime(true),1000));
    }

    /**
     * 返回微秒级字符串
     * @param $msLen 微秒数字保留位数 最大8位
     * @return string
     */
    public static function get_ms_timestr($msLen = 3){
        $str = microtime(); //  0.12289100 1650202912 
        $strArr = explode(" ",$str);
        $msStr = $strArr[0];
        $msStr = substr($msStr,2);
        return sprintf("%s%s",$strArr[1],substr($msStr,0,$msLen));
    }

    /**
     * @param $str
     * @return int
     */
    public static function get_str_num_index($str)
    {
        mb_internal_encoding("UTF-8");
        $index = mb_substr($str,0,1).mb_substr($str,1,1).mb_substr($str,2,1).mb_substr($str,3,1);
        $hash = md5($index);
        $prefix = substr($hash,0,4);
        return hexdec($prefix);
    }

    public static function get_ip($disallowProxy = false )
    {
        if(!$disallowProxy){
            if (getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknow')) {
                $ip = getenv('HTTP_X_FORWARDED_FOR');
            }
            elseif (getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknow')) {
                $ip = getenv('HTTP_CLIENT_IP');
            } elseif (getenv('X-Real-Ip') && strcasecmp(getenv('X-Real-Ip'), 'unknow')) {
                $ip = getenv('X-Real-Ip');
            } else if (getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknow')) {
                $ip = getenv('REMOTE_ADDR');
            } elseif (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'],'unknow')){
                $ip = $_SERVER['REMOTE_ADDR'];
            } else {
                $ip = '0.0.0.0';
            }
        }
        else{
            if (getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknow')) {
                $ip = getenv('REMOTE_ADDR');
            } elseif (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'],'unknow')){
                $ip = $_SERVER['REMOTE_ADDR'];
            } else {
                $ip = '0.0.0.0';
            }
        }
        return $ip;
    }


    /**
     * POST 请求
     * @param string $url
     * @param array $param
     * @param int $timeout
     * @return string content
     */
    public static function httpPost($url, $param, $timeout = 10,$userAgent="Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36",$header = [])
    {
        if (is_array($param) && count($param)) {
            $param = http_build_query($param);
        }
        $oCurl = curl_init();
        if (stripos($url, "https://") !== FALSE) {
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, FALSE);
            curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1
        }
        curl_setopt($oCurl, CURLOPT_URL, $url);
        curl_setopt($oCurl, CURLOPT_USERAGENT,$userAgent);
        curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($oCurl, CURLOPT_POST, TRUE);
        curl_setopt($oCurl, CURLOPT_POSTFIELDS, $param);
        curl_setopt($oCurl, CURLOPT_TIMEOUT, intval($timeout));
        if(count($header) > 0){
            curl_setopt($oCurl, CURLOPT_HTTPHEADER, $header);
        }
        $sContent = curl_exec($oCurl);
        curl_close($oCurl);
        return $sContent;

    }

    /**
     * get 请求
     * @param string $url
     * @param int $timeout
     * @return string content
     */
    public static function httpGet($url, $timeout = 10 ,$header = [],$userAgent="Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36")
    {
        $oCurl = curl_init();
        if (stripos($url, "https://") !== FALSE) {
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, FALSE);
            curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1
        }
        curl_setopt($oCurl, CURLOPT_URL, $url);
        //# 代理 fordebug
//        curl_setopt($oCurl,CURLOPT_PROXY,"127.0.0.1");
//        curl_setopt($oCurl,CURLOPT_PROXYPORT,1080);
        curl_setopt($oCurl, CURLOPT_USERAGENT,$userAgent);
        curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($oCurl, CURLOPT_TIMEOUT, intval($timeout));
        if(count($header) > 0){
            curl_setopt($oCurl, CURLOPT_HTTPHEADER, $header);
        }
        $sContent = curl_exec($oCurl);
        curl_close($oCurl);
        return $sContent;
    }

    /**
     * json 请求 (传入返回都为json)
     * @param string $url
     * @param array $postData
     * @param int $timeout
     * @return string content
     */
    public static function httpJsonp($url,array $postData, $timeout = 30,$header = [],$userAgent="Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36"){
        $oCurl = curl_init();
        if (stripos($url, "https://") !== FALSE) {
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, FALSE);
            curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1
        }

        $strPOST = json_encode($postData);
        array_unshift($header,'Content-Type: application/json','Content-Length: ' . strlen($strPOST));

        curl_setopt($oCurl, CURLOPT_URL, $url);
        curl_setopt($oCurl, CURLOPT_USERAGENT,$userAgent);
        curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($oCurl, CURLOPT_POST, true);
        curl_setopt($oCurl, CURLOPT_POSTFIELDS, $strPOST);
        if (!is_null($timeout)) {
            curl_setopt($oCurl, CURLOPT_TIMEOUT, intval($timeout));
        }
        if(count($header) > 0){
            curl_setopt($oCurl, CURLOPT_HTTPHEADER, $header);
        }
        $sContent = curl_exec($oCurl);
        curl_close($oCurl);
        $res = json_decode($sContent,true);
        if(is_array($res)){
            return $res;
        }
        else{
            return null;
        }
    }

    /**
     * 异步请求
     * @param $url
     * @param $param
     */
    public static function ajaxHttp($url, $param, $timeout_ms = 50,$header = [])
    {
        $oCurl = curl_init();
        if (stripos($url, "https://") !== FALSE) {
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, false);
            curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1
        }
        if (is_string($param)) {
            $strPOST = $param;
        } else {
            $aPOST = array();
            foreach ($param as $key => $val) {
                $aPOST[] = $key . "=" . urlencode($val);
            }
            $strPOST = join("&", $aPOST);
        }
        curl_setopt($oCurl, CURLOPT_NOSIGNAL, 1);
        curl_setopt($oCurl, CURLOPT_URL, $url);
        curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($oCurl, CURLOPT_TIMEOUT_MS, $timeout_ms);//超时为1毫秒
        curl_setopt($oCurl, CURLOPT_POST, true);
        curl_setopt($oCurl, CURLOPT_POSTFIELDS, $strPOST);
        if(count($header) > 0){
            curl_setopt($oCurl, CURLOPT_HTTPHEADER, $header);
        }
        curl_exec($oCurl);
        curl_close($oCurl);
    }

    /**
     * 判断是否为WINDOWS系统
     * @return bool
     */
    public static function isWin(){
        return strstr(PHP_OS, 'WIN') !== FALSE;
    }

    /**
     * 
     */
    public static function make_in_range($val,$min,$max){
        if($val < $min){
            $val = $min;
        }
        else if($val > $max){
            $val = $max;
        }
        return $val;
    }

    public static function as_regular_filename($str){
        $chars = array("\\", "/", ":", "*", "?", "\"", "\'", "<", ">", "|");
        $name = str_replace($chars,' ',$str);   
        if(self::isWin()){
            $name = iconv("UTF-8","GB2312//TRANSLIT",$name);
        }     
        return $name;
    }
}